// ==UserScript== // @name 云展网PDF下载 YunZhanDownloader // @namespace https://github.com/lcandy2/YunZhanDownloader // @version 1.1 // @author lcandy2 // @description 从云展网下载PDF书籍 // @license MIT // @icon https://book.yunzhan365.com/favicon.ico // @match *://book.yunzhan365.com/*/*/mobile/* // @require https://unpkg.com/jspdf@2.5.1/dist/jspdf.umd.min.js // @require https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js // @run-at document-end // ==/UserScript== (function ($, jspdf) { 'use strict'; const getFliphtml5Pages = async () => { try { const scriptTag = document.querySelector('script[src*="javascript/config.js"]'); if (!scriptTag) { throw new Error("Script tag not found"); } const src = scriptTag.getAttribute("src"); const response = await fetch(src); const scriptContent = await response.text(); const configMatch = scriptContent.match(/var htmlConfig = ({.*});/); if (!configMatch || !configMatch[1]) { throw new Error("htmlConfig not found in the script"); } const configObject = JSON.parse(configMatch[1]); const fliphtml5_pages = configObject.fliphtml5_pages; return fliphtml5_pages; } catch (error) { console.error("Error:", error.message); } }; const getImageData = async (url) => { const response = await fetch(url); const blob = await response.blob(); return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = () => resolve(reader.result); reader.onerror = reject; reader.readAsDataURL(blob); }); }; const addDownloadBtn = (listener) => { let observer; const checkAndProcessButtonBar = () => { const $buttonBar = $("div.fbTopBar div.buttonBar"); const buttonBarAvailable = $buttonBar.length; const $shareTitle = $("div.share_form p.form_title"); const $shareCloseBtn = $("div.share_form img.close"); const $shareContent = $("div.share_form div.share_content"); const shareFormAvailable = $shareTitle.length && $shareCloseBtn.length && $shareContent.length; if (buttonBarAvailable && shareFormAvailable) { observer.disconnect(); console.log("Found buttonBar:", $buttonBar); const shareElement = $buttonBar.children().eq(8); const $element = $(`

下载

`); shareElement.html($element); $shareTitle.html("下载"); $shareCloseBtn.remove(); const downloadHtml = $(`

下载《${$("title").text()}》


未开始下载



`); $shareContent.html(downloadHtml); $("#dl-btn").on("click", listener); return shareElement; } }; const observeDOM = (execute) => { observer = new MutationObserver((mutations) => { for (let mutation of mutations) { if (mutation.addedNodes.length) { execute(); break; } } }); observer.observe(document.body, { childList: true, subtree: true }); }; observeDOM(checkAndProcessButtonBar); }; const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); const pdf = new jspdf.jsPDF(); const ConvertToPDF = async (imagePromises) => { const $dlprogress = $("#dl-progress"); const $dlbtn = $("#dl-btn"); $dlbtn.html("下载中..."); $dlbtn.prop("disabled", true); $dlbtn.css("background-color", "#808080"); $dlbtn.css("cursor", "not-allowed"); $dlprogress.html("准备下载..."); const title2 = $("title").text(); try { const images = await Promise.all(imagePromises); for (let index = 0; index < images.length; index++) { const progress = `下载中:${index + 1} / ${images.length} 页`; $dlprogress.html(progress); console.log(`Downloading: ${progress}`); if (index > 0) pdf.addPage(); pdf.addImage(images[index], "WEBP", 0, 0, pdf.internal.pageSize.getWidth(), pdf.internal.pageSize.getHeight()); await delay(1e3); } } catch (error) { console.error("Error processing images:", error); } $dlbtn.html("下载 PDF"); $dlbtn.prop("disabled", false); $dlbtn.css("background-color", "#007bff"); $dlbtn.css("cursor", "pointer"); $dlprogress.html("下载完成"); console.log(`Downloading: ${title2}.pdf`); DownloadConvertedPDF(); $dlbtn.off("click").on("click", DownloadConvertedPDF); }; const DownloadConvertedPDF = async () => { pdf.save(`${title}.pdf`); }; $(async () => { const fliphtml5Pages = await getFliphtml5Pages(); if (!fliphtml5Pages) { console.error("fliphtml5Pages not found"); return; } const imagePromises = fliphtml5Pages.map((page) => getImageData(page.n[0])); const convertToPDF = () => ConvertToPDF(imagePromises); addDownloadBtn(convertToPDF); }); })(jQuery, jspdf);